/**
 * 网络请求封装
 * 基于uni.request封装的请求工具
 */

// 基础配置（所有配置都在这里，不需要外部设置）
const config = {
    baseURL: 'http://localhost:10001', // API基础URL
    timeout: 10000, // 请求超时时间(ms)
    contentType: 'application/json',
    loading: true // 是否显示加载提示
};

// 请求计数器
let loadingCount = 0;

/**
 * 显示加载提示
 */
const showLoading = () => {
    if (config.loading) {
        loadingCount++;
        uni.showLoading({
            title: '加载中...',
            mask: true
        });
    }
};

/**
 * 隐藏加载提示
 */
const hideLoading = () => {
    if (config.loading && loadingCount > 0) {
        loadingCount--;
        if (loadingCount === 0) {
            uni.hideLoading();
        }
    }
};

/**
 * 处理请求URL
 * @param {String} url 请求路径
 * @returns {String} 完整URL
 */
const getFullURL = (url) => {
    if (url.startsWith('http')) {
        return url;
    }
    return config.baseURL + (url.startsWith('/') ? url : '/' + url);
};

/**
 * 获取请求头
 * @returns {Object} 包含token的请求头
 */
const getHeader = () => {
    const header = {
        'Content-Type': config.contentType
    };

    // 从本地存储获取token并添加到请求头
    const token = uni.getStorageSync('token');
    if (token) {
        header.Authorization = token;
    }

    return header;
};

/**
 * 处理Token过期
 */
const handleTokenExpired = () => {
    // 清除登录信息
    uni.removeStorageSync('token');
    uni.removeStorageSync('userInfo');

    // 提示用户
    uni.showToast({
        title: '登录已过期，请重新登录',
        icon: 'none',
        duration: 2000
    });

    // 延迟跳转到登录页面
    setTimeout(() => {
        uni.navigateTo({
            url: '/pages/login/index'
        });
    }, 1500);
};

/**
 * 统一请求方法
 * @param {String} url 请求路径
 * @param {String} method 请求方法GET、POST等
 * @param {Object} data 请求参数
 * @param {Boolean} showLoading 是否显示加载提示
 * @returns {Promise} 请求Promise
 */
const request = (url, method = 'GET', data = {}, showLoadingFlag = true) => {
    // 是否显示加载提示
    config.loading = showLoadingFlag;

    // 如果需要，显示加载提示
    if (config.loading) {
        showLoading();
    }

    return new Promise((resolve, reject) => {
        uni.request({
            url: getFullURL(url),
            method: method,
            data: data,
            header: getHeader(),
            timeout: config.timeout,
            success: (res) => {
                // 隐藏加载提示
                if (config.loading) {
                    hideLoading();
                }

                if (res.statusCode === 200) {
                    // 业务状态码处理
                    const result = res.data;

                    // 成功状态
                    if (result.code === 0 || result.code === 200 || result.code === 20000) {
                        resolve(result);
                    }
                    // Token失效
                    else if (result.code === 401 || result.code === 40101 ||
                        (result.message && (result.message.includes('token') || result.message.includes('登录')))) {
                        handleTokenExpired();
                        reject(result);
                    }
                    // 其他错误
                    else {
                        const errMsg = result.message || result.msg || '请求失败';
                        uni.showToast({
                            title: errMsg,
                            icon: 'none',
                            duration: 2000
                        });
                        reject(result);
                    }
                }
                // HTTP错误状态码
                else {
                    let errMsg = '网络请求错误';

                    switch (res.statusCode) {
                        case 401:
                            handleTokenExpired();
                            errMsg = '登录已过期，请重新登录';
                            break;
                        case 403:
                            errMsg = '拒绝访问';
                            break;
                        case 404:
                            errMsg = '请求的资源不存在';
                            break;
                        case 500:
                            errMsg = '服务器错误';
                            break;
                        default:
                            errMsg = `网络错误(${res.statusCode})`;
                    }

                    uni.showToast({
                        title: errMsg,
                        icon: 'none',
                        duration: 2000
                    });

                    reject({ code: res.statusCode, message: errMsg });
                }
            },
            fail: (err) => {
                // 隐藏加载提示
                if (config.loading) {
                    hideLoading();
                }

                // 处理错误信息
                let errMsg = '网络请求失败，请检查网络';
                if (err.errMsg) {
                    if (err.errMsg.includes('timeout')) {
                        errMsg = '请求超时，请稍后再试';
                    }
                }

                uni.showToast({
                    title: errMsg,
                    icon: 'none',
                    duration: 2000
                });

                reject(err);
            }
        });
    });
};

// 常用请求方法封装
const http = {
    /**
     * GET请求
     * @param {String} url 请求路径
     * @param {Object} data 请求参数
     * @param {Boolean} showLoading 是否显示加载提示
     * @returns {Promise} 请求Promise
     */
    get: (url, data = {}, showLoading = true) => {
        return request(url, 'GET', data, showLoading);
    },

    /**
     * POST请求
     * @param {String} url 请求路径
     * @param {Object} data 请求参数
     * @param {Boolean} showLoading 是否显示加载提示
     * @returns {Promise} 请求Promise
     */
    post: (url, data = {}, showLoading = true) => {
        return request(url, 'POST', data, showLoading);
    },

    /**
     * PUT请求
     * @param {String} url 请求路径
     * @param {Object} data 请求参数
     * @param {Boolean} showLoading 是否显示加载提示
     * @returns {Promise} 请求Promise
     */
    put: (url, data = {}, showLoading = true) => {
        return request(url, 'PUT', data, showLoading);
    },

    /**
     * DELETE请求
     * @param {String} url 请求路径
     * @param {Object} data 请求参数
     * @param {Boolean} showLoading 是否显示加载提示
     * @returns {Promise} 请求Promise
     */
    delete: (url, data = {}, showLoading = true) => {
        return request(url, 'DELETE', data, showLoading);
    },

    /**
     * 上传文件
     * @param {String} url 上传路径
     * @param {String} filePath 文件路径
     * @param {String} name 文件对应的key
     * @param {Object} formData 附加的表单数据
     * @returns {Promise} 上传Promise
     */
    upload: (url, filePath, name = 'file', formData = {}) => {
        showLoading();

        return new Promise((resolve, reject) => {
            uni.uploadFile({
                url: getFullURL(url),
                filePath: filePath,
                name: name,
                formData: formData,
                header: getHeader(),
                success: (res) => {
                    hideLoading();

                    if (res.statusCode === 200) {
                        // 尝试解析响应数据
                        try {
                            const result = JSON.parse(res.data);
                            if (result.code === 0 || result.code === 200 || result.code === 20000) {
                                resolve(result);
                            } else {
                                const errMsg = result.message || result.msg || '上传失败';
                                uni.showToast({
                                    title: errMsg,
                                    icon: 'none',
                                    duration: 2000
                                });
                                reject(result);
                            }
                        } catch (e) {
                            resolve(res.data);
                        }
                    } else {
                        uni.showToast({
                            title: '上传失败，服务器异常',
                            icon: 'none',
                            duration: 2000
                        });
                        reject(res);
                    }
                },
                fail: (err) => {
                    hideLoading();
                    uni.showToast({
                        title: '上传失败，请检查网络',
                        icon: 'none',
                        duration: 2000
                    });
                    reject(err);
                }
            });
        });
    }
};

// 暴露给外部使用的方法
export default http; 